package org.dreamwork.jasmine2.web.controls;

import org.dreamwork.jasmine2.engine.IPostbackHandler;
import org.dreamwork.jasmine2.engine.IClickable;
import org.dreamwork.jasmine2.engine.HttpContext;
import org.dreamwork.jasmine2.engine.IValidatable;
import org.dreamwork.jasmine2.events.*;
import org.dreamwork.jasmine2.web.IWebControl;
import org.dreamwork.jasmine2.web.html.Table;
import org.dreamwork.jasmine2.web.html.TableRow;
import org.dreamwork.jasmine2.web.html.TableCell;
import org.dreamwork.jasmine2.util.StringConverter;
import org.dreamwork.util.NameValueCollection;
import org.dreamwork.peony.DataBinder;

import java.util.*;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * Created by IntelliJ IDEA.
 * User: seth
 * Date: 2009-7-27
 * Time: 17:17:28
 */
public class ButtonGroup extends WebContainer implements IPostbackHandler, IClickable, IValidatable {
    private ClickableDelegate clickDelegate = new ClickableDelegate ();
    private List data;
    private String textField;
    private String type = "checkbox";
    private Set<String> value = new HashSet<String> ();

    private String layout = "flow";
    private int columns = 1;

    private ValidatableDelegate validateDelegate = new ValidatableDelegate ();

    private static final String[] VALID_LAYOUT = {"flow", "box", "columns"};

    public Set<String> getValue () {
        return value;
    }

    public void setValue (String value) {
        String[] parts = value.split (",");
        for (String part : parts) this.value.add (part.trim ());
    }

    public String getTextField () {
        return textField;
    }

    public void setTextField (String textField) {
        this.textField = textField;
    }

    public String getType () {
        return type;
    }

    public void setType (String type) {
        if (!("radio".equalsIgnoreCase (type) || "checkbox".equalsIgnoreCase (type)))
            throw new IllegalArgumentException ("invalid value for attribute type: " + type);
        this.type = type;
    }

    public String getLayout () {
        return layout;
    }

    public void setLayout (String layout) {
        if (!isValidLayout (layout))
            throw new IllegalArgumentException ("invalid value for attribute layout: " + layout);
        this.layout = layout;
    }

    public int getColumns () {
        return columns;
    }

    public void setColumns (int columns) {
        this.columns = columns;
    }

    public void addClickListener (IClickListener listener) {
        clickDelegate.addClickListener (listener);
    }

    public void removeClickListener (IClickListener listener) {
        clickDelegate.removeClickListener (listener);
    }

    public void fireControlClicked (IWebControl sender) throws EventException {
        clickDelegate.fireControlClicked (sender);
    }

    public IClickListener[] getClickListeners () {
        return clickDelegate.getClickListeners ();
    }

    public void postbackData (NameValueCollection props) {
        String receive = props.getValue (getName ());
        if (receive != null)
            setValue (receive);
    }

    @SuppressWarnings ("unchecked")
    protected void loadViewState (Object savedState) throws IOException {
        super.loadViewState (savedState);
        data = (List) stateManager.get ("data");
        Object value = stateManager.get ("value");
        if (value != null)
            oldAttributes.put ("value", value);
    }

    public void onDataBind (Object sender) throws EventException {
        if (dataSource == null || valueField == null || textField == null)
            return;
        data = DataBinder.parseDataSource (dataSource);

        if (viewStateEnabled)
            stateManager.put ("data", data);
    }

    public void createChildControls () {
        int offset = childControls.count ();

        ArrayList<CheckBox> set = new ArrayList<CheckBox> ();

        for (int i = 0; i < childControls.count (); i++) {
            CheckBox box = (CheckBox) childControls.getControl (i);
            if (box.isChecked ()) set.add (box);
        }

        if (data != null) {
            if (!"columns".equalsIgnoreCase (layout)) {
                for (int i = 0; i < data.size (); i++) {
                    Object container = data.get (i);
                    CheckBox box = createCheckBox (i + offset);
                    Object value = DataBinder.eval (container, valueField);
                    Object text = DataBinder.eval (container, textField);
                    box.setValue (StringConverter.contvertToString (value));
                    box.setText (StringConverter.contvertToString (text));

                    if (StringConverter.contains (this.value, value)) {
                        box.setChecked (true);
                        set.add (box);
                    }

                    box.setPage (page);
                    addControl (box);
                    if ("box".equalsIgnoreCase (layout))
                        childControls.add (id + "_dumy_" + i, new Literal ("<br>"));
                }
            } else {
                Table table = new Table ();
                table.setId (getClientId () + "_dumy_table");
                table.setAttribute ("cellpadding", "0");
                table.setAttribute ("cellspacing", "0");
                table.setPage (page);
                TableRow row = null;
                for (int i = 0; i < data.size (); i++) {
                    if (i % columns == 0) {
                        row = new TableRow ();
                        table.addRow (row);
                    }
                    TableCell cell = new TableCell ();
                    Object container = data.get (i);
                    CheckBox box = createCheckBox (i + offset);
                    Object value = DataBinder.eval (container, valueField);
                    Object text = DataBinder.eval (container, textField);
                    box.setValue (StringConverter.contvertToString (value));
                    box.setText (StringConverter.contvertToString (text));

                    if (StringConverter.contains (this.value, value)) {
                        box.setChecked (true);
                        set.add (box);
                    }

                    box.setPage (page);
                    cell.addControl (box);
                    if (row != null) row.addCell (cell);
                }

                childControls.add (table.getId (), table);
            }
        }

        if ("radio".equalsIgnoreCase (type)) for (int i = 0; i < set.size () - 1; i++) {
            set.get (i).setChecked (false);
        }

        childControlCreated = true;
    }

    public void addControl (IWebControl control) {
        if (!(control instanceof CheckBox))
            throw new IllegalArgumentException (control.getClass ().getName ());
        super.addControl (control);
    }

    public void onPrerender (IWebControl sender, HttpContext context) throws EventException {
        super.onPrerender (sender, context);
        attrs.remove ("id");
        attrs.remove ("value");
        attrs.remove ("name");
        for (int i = 0; i < childControls.count (); i++) {
            IWebControl control = childControls.getControl (i);
            if (control instanceof CheckBox) {
                CheckBox box = (CheckBox) control;
                box.attrs.putAll (attrs);
                box.style.putAll (style);
                box.dynamicAttributes.putAll (dynamicAttributes);
            }
        }
    }

    @Override
    protected void beginTag (PrintWriter writer) throws IOException {
        // do nothing
    }

    @Override
    protected void endTag (PrintWriter writer) {
        // do nothing
    }

    private CheckBox createCheckBox (int index) {
        CheckBox box;
        if ("checkbox".equalsIgnoreCase (type))
            box = new CheckBox ();
        else
            box = new Radio ();

        box.setPage (page);
        box.setId (id + "_" + index);
        box.setName (getName ());
        box.setHttpContext (context);
        box.setAutoPostback (autoPostback);
        box.setRunAtServer (runAtServer);
        box.init ();
        return box;
    }

    private boolean isValidLayout (String layout) {
        for (String s : VALID_LAYOUT)
            if (s.equalsIgnoreCase (layout))
                return true;
        return false;
    }

    public void addValidateListener (IValidateListener listener) {
        validateDelegate.addValidateListener (listener);
    }

    public void removeValidateListener (IValidateListener listener) {
        validateDelegate.removeValidateListener (listener);
    }

    public IValidateListener[] getValidateListners () {
        return validateDelegate.getValidateListners ();
    }

    public boolean fireValidateListeners (IWebControl sender) {
        return validateDelegate.fireValidateListeners (sender);
    }
}